use std::{rc::Rc, cell::RefCell};

use crate::{instructions::base::Instruction, rtda::Frame};



#[derive(Debug, Default)]
pub struct RETURN {}

impl Instruction for RETURN {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let thread = frame.borrow().get_thread();
        thread.lock().unwrap().pop_frame();
    }
}

#[derive(Debug, Default)]
pub struct ARETURN {}

impl Instruction for ARETURN {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let thread = frame.borrow().get_thread();
        let mut t_mut = thread.lock().unwrap();
        let current_frame = t_mut.pop_frame();
        let invoker_frame = t_mut.current_frame();
        let ret_val = current_frame.borrow().get_operand_stack().borrow_mut().pop_ref();
        invoker_frame.borrow().get_operand_stack().borrow_mut().push_ref(ret_val);
    }
}

#[derive(Debug, Default)]
pub struct DRETURN {}

impl Instruction for DRETURN {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let thread = frame.borrow().get_thread();
        let mut t_mut = thread.lock().unwrap();
        let current_frame = t_mut.pop_frame();
        let invoker_frame = t_mut.current_frame();
        let ret_val = current_frame.borrow().get_operand_stack().borrow_mut().pop_double();
        invoker_frame.borrow().get_operand_stack().borrow_mut().push_double(ret_val);    }
}

#[derive(Debug, Default)]
pub struct FRETURN {}

impl Instruction for FRETURN {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let thread = frame.borrow().get_thread();
        let mut t_mut = thread.lock().unwrap();
        let current_frame = t_mut.pop_frame();
        let invoker_frame = t_mut.current_frame();
        let ret_val = current_frame.borrow().get_operand_stack().borrow_mut().pop_float();
        invoker_frame.borrow().get_operand_stack().borrow_mut().push_float(ret_val);    }
}

#[derive(Debug, Default)]
pub struct IRETURN {}

impl Instruction for IRETURN {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let thread = frame.borrow().get_thread();
        let mut t_mut = thread.lock().unwrap();
        let current_frame = t_mut.pop_frame();
        let invoker_frame = t_mut.current_frame();
        let ret_val = current_frame.borrow().get_operand_stack().borrow_mut().pop_int();
        invoker_frame.borrow().get_operand_stack().borrow_mut().push_int(ret_val);    }
}

#[derive(Debug, Default)]
pub struct LRETURN {}

impl Instruction for LRETURN {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let thread = frame.borrow().get_thread();
        let mut t_mut = thread.lock().unwrap();
        let current_frame = t_mut.pop_frame();
        let invoker_frame = t_mut.current_frame();
        let ret_val = current_frame.borrow().get_operand_stack().borrow_mut().pop_long();
        invoker_frame.borrow().get_operand_stack().borrow_mut().push_long(ret_val);    }
}
